﻿Imports System.Threading
Imports System.ComponentModel
Imports System.ServiceModel
Imports System.IO
Imports ajayumi.develop.win32.Transport.Wcf.Contracts
Imports ajListView = ajayumi.develop.VBasic.Win.Controls.ListView

Public Class UploadFileTask

#Region "variable"
    Private m_Thread As Thread = Nothing
    Private m_LvItem As ListViewItem = Nothing

#End Region

#Region "property"

    Private m_TransFileInfo As TransFileInfo = Nothing
    Public Property TransFileInfo() As TransFileInfo
        Get
            Return m_TransFileInfo
        End Get
        Set(ByVal value As TransFileInfo)
            m_TransFileInfo = value
        End Set
    End Property


    Private m_Lv As ajListView = Nothing
    Public Property Lv() As ajListView
        Get
            Return m_Lv
        End Get
        Set(ByVal value As ajListView)
            m_Lv = value
        End Set
    End Property


    Private m_TxMsg As TextBox
    Public Property TxtMsg() As TextBox
        Get
            Return m_TxMsg
        End Get
        Set(ByVal value As TextBox)
            m_TxMsg = value
        End Set
    End Property


    Private m_TransportStauts As TransportStatus = TransportStatus.Waiting
    Public ReadOnly Property NewProperty() As TransportStatus
        Get
            Return m_TransportStauts
        End Get
    End Property


#End Region

#Region "private method"

    Private Sub callUploadFileService()
        Me.m_TransportStauts = TransportStatus.Transporting

        Me.uploadItem(Settings.STAUTS_KEY, Me.m_TransportStauts.ToString())
        Dim _UploadFileCallback As New UploadFileCallback()
        With _UploadFileCallback
            AddHandler .UploadProgressChanged, AddressOf Me.UploadProgressChanged
            AddHandler .UploadCompleted, AddressOf Me.UploadCompleted
        End With
        Dim _Factory As New DuplexChannelFactory(Of IUploadFile)(New InstanceContext(_UploadFileCallback), "UploadFile")
        Dim _UploadFile As IUploadFile = _Factory.CreateChannel()

        Using DirectCast(_UploadFile, IDisposable)

            Using _FileStream As New FileStream(Me.m_TransFileInfo.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read)
                Me.m_TransFileInfo.FileLength = _FileStream.Length
                Me.uploadItem(Settings.FILELENGTH_KEY, CStr(Me.m_TransFileInfo.FileLength))

                Dim _BufferSize As Integer = My.Settings.BufferSize  '1024 * 1024 * 8
                Dim _Read As Integer = 0

                Me.m_TransFileInfo.FileData = getData(_FileStream, _BufferSize, _Read)
                While _Read > 0
                    _UploadFile.TransportFile(Me.m_TransFileInfo)
                    Me.m_TransFileInfo.Position += _Read

                    Me.m_TransFileInfo.FileData = getData(_FileStream, _BufferSize, _Read)
                End While

            End Using

        End Using
        Me.disposeThread()
    End Sub

    Private Function getData(ByVal fileStrean As FileStream, ByVal bufferSize As Integer, ByRef readCount As Integer) As Byte()
        Dim _Data() As Byte = Nothing

        If fileStrean.Length > bufferSize Then
            If fileStrean.Length - fileStrean.Position > bufferSize Then
                ReDim _Data(bufferSize - 1)
            Else
                ReDim _Data(fileStrean.Length - fileStrean.Position - 1)
            End If
        Else
            ReDim _Data(fileStrean.Length - 1)
        End If

        readCount = fileStrean.Read(_Data, 0, _Data.Length)

        Return _Data
    End Function

    Private Sub disposeThread()
        If Me.m_Thread IsNot Nothing Then
            Me.m_Thread.Abort()
            Me.m_Thread = Nothing
        End If
    End Sub

    Private Sub uploadItem(ByVal key As String, ByVal value As String)
        If Me.Lv.InvokeRequired Then
            Me.Lv.Invoke(New Action(Of String, String)(AddressOf Me.uploadItem), New Object() {key, value})
        Else
            Me.m_LvItem.SubItems(key).Text = value
        End If
    End Sub

#End Region

#Region "public method"

    Public Sub [Start]()
        If Me.m_TransportStauts = TransportStatus.Waiting OrElse _
           Me.m_TransportStauts = TransportStatus.Error Then
            Me.m_Thread = New Thread(New ThreadStart(AddressOf Me.callUploadFileService))
            Me.m_Thread.Start()
        End If
    End Sub

    Public Sub AddItem(ByVal item As ListViewItem)
        If Me.Lv.InvokeRequired Then
            Me.Lv.Invoke(New Action(Of ListViewItem)(AddressOf Me.AddItem), New Object() {item})
        Else
            Me.m_LvItem = item
            Me.m_LvItem.Tag = Me

            Me.Lv.Invoke(New Action(Of ListViewItem)(AddressOf Me.Lv.Items.Add), New Object() {item})
        End If
    End Sub


#End Region

    Sub UploadCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
        Dim _TransFileInfo As TransFileInfo = DirectCast(e.UserState, TransFileInfo)
        If e.Error Is Nothing Then
            Me.m_TransportStauts = TransportStatus.Transported
            ControlHelper.AppendText(Me.TxtMsg, String.Format("上传文件 {0} 完毕{1}", Path.GetFileNameWithoutExtension(_TransFileInfo.FilePath), vbCrLf))
        Else
            ControlHelper.AppendText(Me.TxtMsg, String.Format("上传文件 {0} 发生错误：{1}{2}", Path.GetFileName(_TransFileInfo.FilePath), e.Error.Message, vbCrLf))
            Me.m_TransportStauts = TransportStatus.Error
        End If

        Me.uploadItem(Settings.STAUTS_KEY, Me.m_TransportStauts.ToString())
    End Sub

    Sub UploadProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
        Dim _TransFileInfo As TransFileInfo = DirectCast(e.UserState, TransFileInfo)
        ControlHelper.AppendText(Me.TxtMsg, String.Format("文件 {0} 当前上传进度：{1}%{2}", Path.GetFileName(_TransFileInfo.FilePath), e.ProgressPercentage, vbCrLf))
        Me.uploadItem(Settings.PROGRESS_KEY, CStr(e.ProgressPercentage))
    End Sub

End Class
